package com.easychat.controller;

import com.easychat.annotation.GlobalInterceptor;
import com.easychat.constants.Constants;
import com.easychat.entity.config.AppConfig;
import com.easychat.entity.dto.MessageSendDTO;
import com.easychat.entity.dto.TokenUserInfoDTO;
import com.easychat.entity.enums.MessageTypeEnum;
import com.easychat.entity.enums.ResponseCodeEnum;
import com.easychat.entity.po.ChatMessage;
import com.easychat.entity.vo.ResponseVO;
import com.easychat.exception.BusinessException;
import com.easychat.service.ChatMessageService;
import com.easychat.service.ChatSessionUserService;
import com.easychat.utils.StringTools;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Length;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

@RestController("chatController")
@RequestMapping("/chat")
@Validated
//@Slf4j
public class ChatController extends ABaseController{

    @Resource
    private ChatMessageService chatMessageService;
    @Resource
    private ChatSessionUserService chatSessionUserService;
    @Resource
    private AppConfig appConfig;

    @RequestMapping("/sendMessage")
    @GlobalInterceptor
    public ResponseVO sendMessage(
            HttpServletRequest request,
            @NotEmpty String contactId,
            @NotEmpty @Length(max = 500, message = "发送消息的长度不能超过500") String messageContent,
            @NotNull Integer messageType,
            Long fileSize,
            String fileName,
            Integer fileType
    ) {
        TokenUserInfoDTO tokenUserInfoDTO = getTokenUserInfoDTO(request);

        ChatMessage chatMessage = new ChatMessage();

        chatMessage.setContactId(contactId);
        chatMessage.setMessageContent(messageContent);
        chatMessage.setMessageType(messageType);
        chatMessage.setFileName(fileName);
        chatMessage.setFileSize(fileSize);
        chatMessage.setFileType(fileType);

        MessageSendDTO messageSendDTO = chatMessageService.saveMessage(chatMessage, tokenUserInfoDTO);

        return getSuccessResponseVO(messageSendDTO);
    }

    /**
     * 聊天上传文件到服务端
     * @param request
     * @param messageId 消息ID
     * @param file 文件
     * @param cover 封面
     * @return
     */
    @RequestMapping("/uploadFile")
    @GlobalInterceptor
    public ResponseVO uploadFile(
            HttpServletRequest request,
            @NotNull
            Long messageId,
            @NotNull
            MultipartFile file,
            @NotNull
            MultipartFile cover
    ) {
        TokenUserInfoDTO tokenUserInfoDTO = getTokenUserInfoDTO(request);
        chatMessageService.saveMessageFile(tokenUserInfoDTO.getUserId(), messageId, file, cover);
        return getSuccessResponseVO(null);
    }

    /**
     * 从服务端下载文件
     * @param request
     * @param fileId 文件ID
     * @param showCover 是否展示封面
     * @return
     */
    @RequestMapping("/downloadFile")
    @GlobalInterceptor
    public void downloadFile(
            HttpServletRequest request,
            HttpServletResponse response,
            @NotEmpty
            String fileId,
            @NotNull
            Boolean showCover
    ) {
        TokenUserInfoDTO tokenUserInfoDTO = getTokenUserInfoDTO(request);
        OutputStream outputStream = null;
        FileInputStream fileInputStream = null;
        try {
            File file = null;
            //1. 获取fileId对应的文件对象
            if (!StringTools.isNumber(fileId)) {
                //fileId不是纯数字，对应头像文件 比如U12345678.png
                String avatarFolderName = Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_AVATAR;
                //拼接fileId对应的头像文件路径
                String avatarPath = appConfig.getProjectFolder() + avatarFolderName + fileId + Constants.IMAGE_EXTENSION;
                if (showCover) {
                    //需要展示封面
                    avatarPath = avatarPath + Constants.COVER_IMAGE_EXTENSION;//封面命名方法
                }
                file = new File(avatarPath);
                if (!file.exists()) {
                    throw new BusinessException(ResponseCodeEnum.CODE_602);//要下载文件不存在，异常
                }
            } else {
                //fileId是纯数字，对应其他文件
                file = chatMessageService.downloadFile(tokenUserInfoDTO, Long.parseLong(fileId), showCover);
            }
            //2. 服务端将相应的文件通过response进行传输，客户端完成文件下载
            response.setContentType("application/x-msdownload;charset=UTF-8");//设置响应类型，告诉浏览器这是一个下载文件
            response.setHeader("Content-Disposition", "attachment;");//设置文件在浏览器弹出对话框让用户下载
            response.setContentLengthLong(file.length());//文件长度
            fileInputStream = new FileInputStream(file);//从本地读文件
            byte[] buffer = new byte[1024];//缓冲区
            int len = 0;//每次读的长度
            outputStream = response.getOutputStream();//从response获取输出流
            while ((len = fileInputStream.read(buffer)) != -1) {
                //从本地读文件, 同时写入response
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();//写完别忘了刷新
        } catch (Exception e) {
            //log.error("文件下载失败", e);
        } finally {
            //关闭流 顺序：后开的先关
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    //log.error("IO异常", e);
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (Exception e) {
                    //log.error("IO异常", e);
                }
            }
        }
    }
}
